"""
本周建议学习内容：
09. 函数（二）	1、闭包原理
	2、nonlocal和LEGB
	3、匿名函数
	4、生成器函数
	5、冒泡排序
	6、函数执行原理
	7、递归函数
	8、作业之比较大小
	9、作业上下三角打印
	10、选择排序精讲
10. 装饰器	可迭代对象和内建函数
	高阶函数柯里化
	无参装饰器
	带参装饰器
	类型注解和类型检查装饰器
	插入排序
	functools之reduce和partial
	lru_cache和cache原理


完成作业：
1. 什么是高阶函数和闭包并举例说明。
    高阶函数：接受一个（或多个）函数作为参数，或者返回一个函数的函数
    def foo(fn):
        pass

    def fn():
        def wrapper():
            pass
        return wrapper

    闭包：外部函数释放，内部函数存活且内部函数引用外部变量形成闭包
        def foo():
            i = 0
            def inner():
                nonlocal i
                while True:
                    i += 1
                    yield i
            return inner
        foo().__closure__
2. 请列出functools包内的每个函数的功能作用。
    reduce(function, sequence[, initial]) -> value 利用一个双参函数function，将一个序列sequence自左至右合并得到一个值；
    partial(func, *args, **keywords) -> new function with partial application of the given arguments and keywords. 对函数进行封装，func的参数固定下来
    functools.lru_cache(maxsize=128, typed=False) Least-recently-used cache decorator. lru即Least-recently-used，最近最少使用。cache缓存；
        如果maxsize设置为None，则禁用LRU功能，并且缓存可以无限制增长。当maxsize是二的幂时，LRU功能执行得最好
        如果typed设置为True，则不同类型的函数参数将单独缓存。例如，f(3)和f(3.0)将被视为具有不同结果的不同调用
3. 请使用已学习的装饰器相关知识自己实现functools.lru_cache。
def mycache(fn):
    cache_dict = {}
    @wraps(fn)
    def wrapper(*args, **kwargs):
        key = str(fn.__name__)+str(args)+str(kwargs)
        if key in cache_dict:
            return cache_dict[key]
        ret = fn(*args, **kwargs)
        cache_dict[key] = ret
        return ret
    return wrapper

@mycache
def sub(x, y):
    time.sleep(2)
    return x - y

sub(3,y=1)
4. 什么是类型注解并说明其背后的目的。
    类型注解：对函数的形参和返回值的类型说明；辅助作用，非强约束
    目的：辅助检查实参是否与注解类型一致。


"""
